/*
 * Android Runner is a multiplayer GPS game fully written by Xurxo Mendez Perez
 * 
 * Copyright (C) 2009 Xurxo Mendez Perez
 *   
 * This file is part of Android Runner.
 * 
 * Android Runner is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * Android Runner is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with Android Runner.  If not, see <http://www.gnu.org/licenses/>.
 */

package es.sonxurxo.gpsgame.client.cv.common.actions;

import android.app.Activity;
import android.database.sqlite.SQLiteException;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import es.sonxurxo.gpsgame.client.cv.activity.Abandonable;
import es.sonxurxo.gpsgame.client.cv.common.dialogs.CommonDialogs;
import es.sonxurxo.gpsgame.client.cv.util.constants.CustomResultCodes;
import es.sonxurxo.gpsgame.client.model.service.game.HttpGameServiceImpl;
import es.sonxurxo.gpsgame.client.model.service.player.HttpPlayerServiceImpl;
import es.sonxurxo.gpsgame.client.model.service.to.Game;
import es.sonxurxo.gpsgame.client.model.service.to.Player;
import es.sonxurxo.gpsgame.client.util.db.PendingGamesDbAdapter;
import es.sonxurxo.gpsgame.client.util.exception.ServerException;

/**
 * 
 * @author "Xurxo Mendez Perez"
 *
 */
public class CommonActions {
	
	public static final int RESULT_OK = 0;
	public static final int RESULT_SERVER_ERROR = 1;
	public static final int RESULT_CLIENT_ERROR = 2;
	public static final int RESULT_ERROR = 3;
	
	static PendingGamesDbAdapter p;
	
	private static LogoutTask logoutTask;
	private static AbandonGameTask abandonGameTask;
	private static DbDeleteTask dbDeleteTask;

	public static void launchLogoutThread(String login, Activity from) {
		CommonActions cA = new CommonActions();
		logoutTask = cA.new LogoutTask(login, from);
		Thread logoutThread = new Thread(null, logoutTask, "Login");
		logoutThread.start();
		from.showDialog(CommonDialogs.CONNECTING_TO_SERVER_DIALOG_ID);
	}
	
	private void doLogout(Activity from) {
		from.setResult(CustomResultCodes.LOGOUT_RESULT_CODE);
		from.finish();
	}
	
	public static void launchDbDeleteThread(Player player, Activity from) {
		CommonActions cA = new CommonActions();
		dbDeleteTask = cA.new DbDeleteTask(player, from);
		Thread dbDeleteThread = new Thread(null, dbDeleteTask, "DBDelete");
		dbDeleteThread.start();
		from.showDialog(CommonDialogs.CONNECTING_TO_SERVER_DIALOG_ID);
	}
	
	private static void doDeletePending(Player player, Activity from) {
		player.setNumberOfItems(0);
		player.setPoints(0);
		player.setGameId(-1);
		
		((Abandonable)from).doAfterAbandon();
	}

	private void doAbandonGame(Player player, Activity from) {
		launchDbDeleteThread(player, from);
	}
	
	public static void launchAbandonGameThread(Player player, Game game, 
			Activity from) {
		CommonActions cA = new CommonActions();
		abandonGameTask = cA.new AbandonGameTask(player, game.getGameId(), from);
		Thread abandonGameThread = new Thread(null, abandonGameTask, "AbandonGame");
		abandonGameThread.start();
		from.showDialog(CommonDialogs.CONNECTING_TO_SERVER_DIALOG_ID);
	}
	
	private class LogoutHandler extends Handler {

		private Activity from;
		
		public LogoutHandler(Looper looper, Activity from) {
			super(looper);
			this.from = from;
		}
		
		@Override
		public void handleMessage(Message msg) {
			ServerException sE = 
				(ServerException)msg.getData().getSerializable("ServerException");
			if (sE	!= null) {
				try {
					from.dismissDialog(CommonDialogs.CONNECTING_TO_SERVER_DIALOG_ID);
				} catch (Exception e) {
					
				}
				CommonDialogs.errorMessage = sE.getMessage();
				from.showDialog(CommonDialogs.SERVER_ERROR_DIALOG_ID);
	        	return;
	        }
        	Exception e = 
	        	(ServerException)msg.getData().getSerializable("Exception");
	        	if (e != null) {
	        		try {
						from.dismissDialog(CommonDialogs.CONNECTING_TO_SERVER_DIALOG_ID);
					} catch (Exception ee) {
						
					}
					CommonDialogs.errorMessage = e.getLocalizedMessage();
	        		from.showDialog(CommonDialogs.CLIENT_ERROR_DIALOG_ID);
		        	return;
	        	}
			if (msg.getData().getBoolean("result")) {
				doLogout(from);
			}
		}
	}
	
	private class LogoutTask implements Runnable {

		String login;
		Activity from;
		
		LogoutTask(String login, Activity from) {
			this.login = login;
			this.from = from;
		}
		
		public void run() {
			
			LogoutHandler handler = new LogoutHandler(Looper.getMainLooper(), from);
			Bundle data = new Bundle();
			Message msg = new Message();
			try {
				HttpPlayerServiceImpl playerService = new HttpPlayerServiceImpl();
				playerService.logoutPlayer(login);
				data.putBoolean("result", true);
				msg.setData(data);
				handler.sendMessage(msg);
				
			} catch (ServerException e) {
	        	data.putSerializable("ServerException", e);
	        	msg.setData(data);
				handler.sendMessage(msg);
	        } catch (Exception e) {
	        	data.putSerializable("Exception", e);
	        	msg.setData(data);
				handler.sendMessage(msg);
	        }
		}
	}
	
	private class AbandonGameHandler extends Handler {

		Activity from;
		public AbandonGameHandler(Looper looper, Activity from) {
			super(looper);
			this.from = from;
		}
		
		@Override
		public void handleMessage(Message msg) {
			ServerException sE = 
				(ServerException)msg.getData().getSerializable("ServerException");
			if (sE	!= null) {
				try {
					from.dismissDialog(CommonDialogs.CONNECTING_TO_SERVER_DIALOG_ID);
				} catch (Exception e) {
					
				}
				CommonDialogs.errorMessage = sE.getMessage();
				if (sE.getCode() == ServerException.INSTANCE_NOT_FOUND_CODE)
					from.showDialog(CommonDialogs.CONNECTION_LOST_DIALOG_ID);
				else
					from.showDialog(CommonDialogs.SERVER_ERROR_DIALOG_ID);
	        	return;
	        }
        	Exception e = 
	        	(ServerException)msg.getData().getSerializable("Exception");
	        	if (e != null) {
	        		try {
						from.dismissDialog(CommonDialogs.CONNECTING_TO_SERVER_DIALOG_ID);
					} catch (Exception ee) {
						
					}
					
	        		CommonDialogs.errorMessage = e.getLocalizedMessage();
	        		from.showDialog(CommonDialogs.CLIENT_ERROR_DIALOG_ID);
		        	return;
	        	}
	        if (msg.getData().getSerializable("player") != null) {
				Player player = (Player)msg.getData().getSerializable("player");
				doAbandonGame(player, from);
				return;
			}
		}
		
	}
	
	private class AbandonGameTask implements Runnable {

		Player player;
		long gameId;
		Activity from;
		
		AbandonGameTask(Player player, long gameId, Activity from) {
			this.player = player;
			this.gameId = gameId;
			this.from = from;
		}
		
		public void run() {
			
			AbandonGameHandler handler = new AbandonGameHandler(Looper.getMainLooper(),
					from);
			Bundle data = new Bundle();
			Message msg = new Message();
			try {
				HttpGameServiceImpl gameService = new HttpGameServiceImpl();
				gameService.abandonGame(gameId);
	        	data.putSerializable("player", player);
				msg.setData(data);
				handler.sendMessage(msg);
				
			} catch (ServerException e) {
	        	data.putSerializable("ServerException", e);
	        	msg.setData(data);
				handler.sendMessage(msg);
	        } catch (Exception e) {
	        	data.putSerializable("Exception", e);
	        	msg.setData(data);
				handler.sendMessage(msg);
	        }
		}
	}

	private class DbDeleteHandler extends Handler {

		Activity from;
		public DbDeleteHandler(Looper looper, Activity from) {
			super(looper);
			this.from = from;
		}
		
		@Override
		public void handleMessage(Message msg) {
			try {
				from.dismissDialog(CommonDialogs.CONNECTING_TO_SERVER_DIALOG_ID);
			} catch (Exception e) {
				
			}
			SQLiteException e = 
	        	(SQLiteException)msg.getData().getSerializable("SQLiteException");
	        	if (e != null) {
	        		CommonDialogs.errorMessage = e.getLocalizedMessage();
	        		from.showDialog(CommonDialogs.SQLITE_ERROR_DIALOG_ID);
		        	return;
	        	}
			if (msg.getData().getSerializable("player") != null) {
				Player player = (Player)msg.getData().getSerializable("player");
				doDeletePending(player, from);
				return;
			}
		}
	}
	
	private class DbDeleteTask implements Runnable {

		Player player;
		Activity from;
		
		DbDeleteTask(Player player, Activity from) {
			this.player = player;
			this.from = from;
		}
		
		public void run() {
			
			DbDeleteHandler handler = new DbDeleteHandler(Looper.getMainLooper(), from);
			Bundle data = new Bundle();
			Message msg = new Message();
			try {
				p = new PendingGamesDbAdapter(from);
				p.open();
				if (!p.deletePendingGame(player.getLogin())) {
					p.close();
		        	throw new SQLiteException("Could not delete the register");
				}
					
				p.close();				
	        	data.putSerializable("player", player);
				msg.setData(data);
				handler.sendMessage(msg);
			} catch (SQLiteException e) {
				data.putSerializable("SQLiteException", e);
	        	msg.setData(data);
				handler.sendMessage(msg);
			}
		}
	}
}